package cn.edu.swu.miniwebsvr.handler;

import cn.edu.swu.miniwebsvr.core.Config;
import cn.edu.swu.miniwebsvr.core.Handler;
import cn.edu.swu.miniwebsvr.core.Parameter;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;

public class DefaultHandler implements Handler {

    private static final Map<String, String> CONTENT_TYPE_MAP = new HashMap<>();

    static {
        // 常见文件类型的MIME类型映射
        CONTENT_TYPE_MAP.put("html", "text/html; charset=UTF-8");
        CONTENT_TYPE_MAP.put("htm", "text/html; charset=UTF-8");
        CONTENT_TYPE_MAP.put("css", "text/css; charset=UTF-8");
        CONTENT_TYPE_MAP.put("js", "application/javascript; charset=UTF-8");
        CONTENT_TYPE_MAP.put("txt", "text/plain; charset=UTF-8");
        CONTENT_TYPE_MAP.put("jpg", "image/jpeg");
        CONTENT_TYPE_MAP.put("png", "image/png");
        CONTENT_TYPE_MAP.put("gif", "image/gif");
    }

    @Override
    public void handle(Parameter request, OutputStream response) {
        PrintWriter writer = new PrintWriter(new OutputStreamWriter(response, StandardCharsets.UTF_8), true);

        try {
            String requestPath = request.getUrl();

            // 处理根路径，映射到index.html
            if (requestPath.equals("/")) {
                requestPath = "/index.html";
            }

            // 移除开头的斜杠，构建相对路径
            String relativePath = requestPath.substring(1);
            if (relativePath.isEmpty()) {
                relativePath = "index.html";
            }

            // 调试信息
            System.out.println("Looking for file: " + relativePath);

            // 尝试多个可能的webroot位置
            Path filePath = tryFindFile(relativePath);

            if (filePath != null && Files.exists(filePath) && Files.isRegularFile(filePath)) {
                byte[] fileBytes = Files.readAllBytes(filePath);
                String contentType = determineContentType(filePath);

                // 写入 200 OK 响应头
                writer.println("HTTP/1.1 200 OK");
                writer.println("Content-Type: " + contentType);
                writer.println("Content-Length: " + fileBytes.length);
                writer.println("Connection: close");
                writer.println("Server: MiniWebSvr/1.0");
                writer.println();
                writer.flush();

                // 写入文件内容
                response.write(fileBytes);

                System.out.println("DefaultHandler: Successfully served " + filePath + " (" + fileBytes.length + " bytes)");

            } else {
                // 文件不存在
                System.err.println("File not found in any location: " + relativePath);
                sendErrorResponse(writer, 404, "Not Found",
                        "Requested resource <code>" + request.getUrl() + "</code> not found.");
            }

        } catch (IOException e) {
            System.err.println("DefaultHandler error: " + e.getMessage());
            sendErrorResponse(writer, 500, "Internal Server Error",
                    "Server error: " + e.getMessage());
        } finally {
            try {
                response.flush();
            } catch (IOException e) {
                // ignore
            }
        }
    }

    /**
     * 尝试在多个位置查找文件
     */
    private Path tryFindFile(String relativePath) {
        // 尝试1: 编译输出目录
        Path path1 = Paths.get("out/production/webserver/webroot", relativePath);
        System.out.println("Trying path 1: " + path1.toAbsolutePath() + " - exists: " + Files.exists(path1));
        if (Files.exists(path1)) {
            return path1;
        }

        // 尝试2: 项目根目录下的webroot
        Path path2 = Paths.get("webroot", relativePath);
        System.out.println("Trying path 2: " + path2.toAbsolutePath() + " - exists: " + Files.exists(path2));
        if (Files.exists(path2)) {
            return path2;
        }

        // 尝试3: 当前工作目录
        Path path3 = Paths.get(System.getProperty("user.dir"), "webroot", relativePath);
        System.out.println("Trying path 3: " + path3.toAbsolutePath() + " - exists: " + Files.exists(path3));
        if (Files.exists(path3)) {
            return path3;
        }

        // 尝试4: src目录下的webroot（开发时使用）
        Path path4 = Paths.get(System.getProperty("user.dir"), "src", "webroot", relativePath);
        System.out.println("Trying path 4: " + path4.toAbsolutePath() + " - exists: " + Files.exists(path4));
        if (Files.exists(path4)) {
            return path4;
        }

        return null;
    }

    /**
     * 根据文件扩展名确定Content-Type
     */
    private String determineContentType(Path filePath) {
        String fileName = filePath.getFileName().toString();
        int dotIndex = fileName.lastIndexOf('.');

        if (dotIndex > 0) {
            String extension = fileName.substring(dotIndex + 1).toLowerCase();
            String contentType = CONTENT_TYPE_MAP.get(extension);
            if (contentType != null) {
                return contentType;
            }
        }

        return "application/octet-stream";
    }

    /**
     * 发送错误响应
     */
    private void sendErrorResponse(PrintWriter writer, int statusCode, String statusText, String message) {
        try {
            String htmlContent = "<!DOCTYPE html>" +
                    "<html><head><meta charset=\"UTF-8\"><title>" + statusCode + " " + statusText + "</title></head>" +
                    "<body><h1>" + statusCode + " " + statusText + "</h1><p>" + message + "</p></body></html>";

            byte[] contentBytes = htmlContent.getBytes(StandardCharsets.UTF_8);

            writer.println("HTTP/1.1 " + statusCode + " " + statusText);
            writer.println("Content-Type: text/html; charset=UTF-8");
            writer.println("Content-Length: " + contentBytes.length);
            writer.println("Connection: close");
            writer.println();
            writer.print(htmlContent);
            writer.flush();

        } catch (Exception e) {
            System.err.println("Failed to send error response: " + e.getMessage());
        }
    }
}